# [九] Bean的实例化-Bean的销毁
Bean的销毁
在 bean创建完成后就会对这个 bean注册一个销毁的 DisposableBeanAdapter对象,Spring中就是通过DisposableBeanAdapter类负责bean的销毁过工作。
# Bean的销毁入口
├─getBean│ ├─doGetBean│ │ ├─getSingleton│ │ ├─getObjectForBeanInstance│ │ ├─getSingletond│ │ │ ├─beforeSingletonCreation│ │ │ ├─createBean│ │ │ │ ├─doCreateBean│ │ │ │ │ ├─createBeanInstance│ │ │ │ │ ├─applyMergedBeanDefinitionPostProcessors│ │ │ │ │ ├─earlySingletonExposure│ │ │ │ │ ├─addSingletonFactory│ │ │ │ │ ├─populateBean│ │ │ │ │ ├─initializeBean│ │ │ │ │ └─registerDisposableBeanIfNecessary ① bean 的销毁过程入口│ │ │ ├─afterSingletonCreation│ │ │ └─addSingleton
# Bean的销毁过程解析
首先我们来看一下① Bean的销毁过程:
进入 doCreateBean () 方法
类文件: org.springframework.beans.factory.support.
AbstractAutowireCapableBeanFactory
try {
...
//注册bean销毁时的类DisposableBeanAdapter
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
进入 registerDisposableBeanIfNecessary () 方法
类文件: org.springframework.beans.factory.support.
AbstractBeanFactory
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
// 如果是单例 bean
if (mbd.isSingleton()) {
// 对这个bean注册一个销毁的Adapter对象,对给定的bean执行销毁工作
// 过滤了 DestructionAwareBeanPostProcessor 类型的接口
registerDisposableBean(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
else {
// 拿到bean的作用域
Scope scope = this.scopes.get(mbd.getScope());
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
}
scope.registerDestructionCallback(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
}
}
# Bean销毁的核心类
在 bean创建完成后就会对这个 bean注册一个销毁的
DisposableBeanAdapter对象,这个类就是 销毁的核心类DisposableBeanAdapter就是负责bean销毁的类。在这个类中收集了该bean 是否实现了DisposableBean接口,是否配置destroy-method属性,如果有则 执行其destroy() 方法。
问题
① Bean的销毁过程是什么时候触发的呢?
答案
- 1、在Spring 中执行显式关闭上下文,关闭时候会执行实现DisposableBean接口类中的destroy() 方法,如:
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"spring.xml"});
// 以下两种显式关闭都会调用实现了DisposableBean接口类中的destroy() 方法
// 1、显式关闭上下文
context.close();
// 2、显式关闭上下文
context.registerShutdownHook();
- 2、在Web环境中,当
Tomcat关闭的时候就会调用到servlet中的销毁方法,在这个方法中就会最终也会掉用到Spring中DisposableBeanAdapter类的destroy()方法,该方法就会根据前面的收集进行调用。
# servlet中的销毁方法
public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
public ContextLoaderListener() {
}
public ContextLoaderListener(WebApplicationContext context) {
super(context);
}
public void contextInitialized(ServletContextEvent event) {
this.initWebApplicationContext(event.getServletContext());
}
// servlet中的销毁方法
public void contextDestroyed(ServletContextEvent event) {
// 该方法最终会调用Spring的DisposableBeanAdapter类的destroy()
this.closeWebApplicationContext(event.getServletContext());
ContextCleanupListener.cleanupAttributes(event.getServletContext());
}
}
servlet中的
closeWebApplicationContext方法最终也会掉用到Spring中的DisposableBeanAdapter类的destroy()方法,该方法就会根据前面的收集进行调用。